package com.gotop.system.service.impl.system;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gotop.common.constant.RoleConstant;
import com.gotop.common.node.ForestNodeMerger;
import com.gotop.common.utils.ApplicationStringUtils;
import com.gotop.common.utils.auth.SecureUtil;
import com.gotop.entity.system.Role;
import com.gotop.entity.system.RoleMenu;
import com.gotop.mapper.system.RoleDao;
import com.gotop.system.service.system.IRoleMenuService;
import com.gotop.system.service.system.IRoleService;
import com.gotop.vo.system.RoleVO;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;

import javax.validation.constraints.NotEmpty;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @program: cem
 * @description:
 * @author: superfish
 * @create: 2020-12-25 10:21
 **/
@Service
@Validated
@AllArgsConstructor
public class RoleServiceImpl extends ServiceImpl<RoleDao, Role> implements IRoleService {

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private IRoleMenuService roleMenuService;

    @Override
    public IPage<RoleVO> selectRolePage(IPage<RoleVO> page, RoleVO role) {
        return page.setRecords(baseMapper.selectRolePage(page, role));
    }

    @Override
    public List<RoleVO> tree(String tenantId) {
        String userRole = SecureUtil.getUserRole();
        String excludeRole = null;
        if (!contains(ApplicationStringUtils.toStrArray(userRole), RoleConstant.ADMIN)) {
            excludeRole = RoleConstant.ADMIN;
        }
        return ForestNodeMerger.merge(baseMapper.tree(tenantId, excludeRole));
    }

    @Override
    public boolean grant(@NotEmpty List<Long> roleIds, @NotEmpty List<Long> menuIds) {
        // 删除角色配置的菜单集合
        roleMenuService.remove(Wrappers.<RoleMenu>update().lambda().in(RoleMenu::getRoleId, roleIds));
        // 组装配置
        List<RoleMenu> roleMenus = new ArrayList<>();
        roleIds.forEach(roleId -> menuIds.forEach(menuId -> {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setRoleId(roleId);
            roleMenu.setMenuId(menuId);
            roleMenus.add(roleMenu);
        }));
        // 新增配置
        return roleMenuService.saveBatch(roleMenus);
    }

    @Override
    public String getRoleIds(String tenantId, String roleNames) {
        final String[] split = roleNames.split(",");
        List<Role> roleList = baseMapper.selectList(Wrappers.<Role>query().lambda().eq(Role::getTenantId, tenantId).in(Role::getRoleName, split));
        if (roleList != null && roleList.size() > 0) {
            return roleList.stream().map(role -> String.valueOf(role.getId())).distinct().collect(Collectors.joining(","));
        }
        return null;
    }

    @Override
    public List<String> getRoleNames(String roleIds) {
        final String[] split = roleIds.split(",");
        List<Long> longs = new LinkedList<>();
        for (String s : split) {
            longs.add(Long.parseLong(s));
        }
        return baseMapper.getRoleNames(longs);
    }

    @Override
    public Role getOne(Role role) {
        return roleDao.selectOne(new LambdaQueryWrapper<Role>().eq(Role::getId, role.getId()));
    }

    public static <T> boolean contains(@Nullable T[] array, final T element) {
        return array == null ? false : Arrays.stream(array).anyMatch((x) -> {
            return ObjectUtils.nullSafeEquals(x, element);
        });
    }

}
